/*******************************************************************************
*
* (c) Copyright 2014 Freescale Semiconductor
*
****************************************************************************//*!
*
* @file     MCG.h
*
* @author   Salvador Zendejas
*
* @version  0.0.1
*
* @date      Aug 22, 2014
*
* @brief    Multipurpose Clock Generator for Kinetis K.
*
*******************************************************************************/

#ifndef MCG_H_
#define MCG_H_

/*******************************************************************************
* Includes
*******************************************************************************/
#include "derivative.h" /* Include peripheral declarations */
#include "../SysCfg.h" /* Include System Config declarations */
#include "../typedef.h" /* Include typedefs declarations */


/*******************************************************************************
* Constants and macros
*******************************************************************************/
/*just define one of them*/
#define _EXTERNAL_CLK_
//#define _INTERNAL_CLK_

#define KNOW_DIV_CLK		YES

#ifdef _EXTERNAL_CLK_
	
	#define CLKS_bitfield	2u
	#define _Crystal_

	#if (_BOARD_ == FRDM_K64F)
		#define _CLK_			_Clk50MHz_
	#elif (_BOARD_ == FRDM_KL25)

	#endif

	#if (_CLK_ > (32 * MHz))
		#undef _Crystal_
		#define RANGE0	3u
	#elif (_CLK_ < (32 * kHz))
		#define RANGE0	0u
	#elif (_CLK_ >= (3 * MHz) && _CLK_ <= (8 * MHz))
		#define RANGE0	1u
	#else
		#define RANGE0	2u
	#endif
#endif

#ifdef _INTERNAL_CLK_
	#define CLKS_bitfield	1u
#endif

#if (RANGE0 != 0)
	#if (_CLK_ / 32 >= 31250 &&  _CLK_ / 32 < 39063)		
		#define FRDIV 0u
	#elif (_CLK_/64 >= 31250 &&  _CLK_/64 < 39063)		
		#define FRDIV 1u
	#elif (_CLK_/128 >= 31250 &&  _CLK_/128 < 39063)	
		#define FRDIV 2u
	#elif (_CLK_/256 >= 31250 &&  _CLK_/256 < 39063)	
		#define FRDIV 3u
	#elif (_CLK_/512 >= 31250 &&  _CLK_/512 < 39063)	
		#define FRDIV 4u
	#elif (_CLK_/1024 >= 31250 &&  _CLK_/1024 < 39063)	
		#define FRDIV 5u
	#elif (_CLK_/1280 >= 31250 &&  _CLK_/1280 < 39063)	
		#define FRDIV 6u
	#elif (_CLK_/1536 >= 31250 &&  _CLK_/1536 < 39063)	
		#define FRDIV 7u
	#endif
#else
	#if (_CLK_/1 >= 31250 &&  _CLK_/1 < 39063)			
		#define FRDIV 0u
	#elif (_CLK_/2 >= 31250 &&  _CLK_/2 < 39063)		
		#define FRDIV 1u
	#elif (_CLK_/4 >= 31250 &&  _CLK_/4 < 39063)		
		#define FRDIV 2u
	#elif (_CLK_/8 >= 31250 &&  _CLK_/8 < 39063)		
		#define FRDIV 3u
	#elif (_CLK_/16 >= 31250 &&  _CLK_/16 < 39063)		
		#define FRDIV 4u
	#elif (_CLK_/32 >= 31250 &&  _CLK_/32 < 39063)		
		#define FRDIV 5u
	#elif (_CLK_/64 >= 31250 &&  _CLK_/64 < 39063)		
		#define FRDIV 6u
	#elif (_CLK_/128 >= 31250 &&  _CLK_/128 < 39063)	
		#define FRDIV 7u
	#endif
#endif

#if (_CLK_/1 >= 32250 && _CLK_/1 <= 4 * MHz)			
		#define PRDIV 0u
#elif (_CLK_/2 >= 32250 && _CLK_/2 <= 4 * MHz)			
		#define PRDIV 1u
#elif (_CLK_/3 >= 32250 && _CLK_/3 <= 4 * MHz)			
		#define PRDIV 2u
#elif (_CLK_/4 >= 32250 && _CLK_/4 <= 4 * MHz)			
		#define PRDIV 3u
#elif (_CLK_/5 >= 32250 && _CLK_/5 <= 4 * MHz)			
		#define PRDIV 4u
#elif (_CLK_/6 >= 32250 && _CLK_/6 <= 4 * MHz)			
		#define PRDIV 5u
#elif (_CLK_/7 >= 32250 && _CLK_/7 <= 4 * MHz)			
		#define PRDIV 6u
#elif (_CLK_/8 >= 32250 && _CLK_/8 <= 4 * MHz)			
		#define PRDIV 7u
#elif (_CLK_/9 >= 32250 && _CLK_/9 <= 4 * MHz)			
		#define PRDIV 8u
#elif (_CLK_/10 >= 32250 && _CLK_/10 <= 4 * MHz)		
		#define PRDIV 9u
#elif (_CLK_/11 >= 32250 && _CLK_/11 <= 4 * MHz)		
		#define PRDIV 10u
#elif (_CLK_/12 >= 32250 && _CLK_/12 <= 4 * MHz)		
		#define PRDIV 11u
#elif (_CLK_/13 >= 32250 && _CLK_/13 <= 4 * MHz)		
		#define PRDIV 12u
#elif (_CLK_/14 >= 32250 && _CLK_/14 <= 4 * MHz)		
		#define PRDIV 13u
#elif (_CLK_/15 >= 32250 && _CLK_/15 <= 4 * MHz)		
		#define PRDIV 14u
#elif (_CLK_/16 >= 32250 && _CLK_/16 <= 4 * MHz)		
		#define PRDIV 15u
#elif (_CLK_/17 >= 32250 && _CLK_/17 <= 4 * MHz)		
		#define PRDIV 16u
#elif (_CLK_/18 >= 32250 && _CLK_/18 <= 4 * MHz)		
		#define PRDIV 17u
#elif (_CLK_/19 >= 32250 && _CLK_/19 <= 4 * MHz)		
		#define PRDIV 18u
#elif (_CLK_/20 >= 32250 && _CLK_/20 <= 4 * MHz)		
		#define PRDIV 19u
#elif (_CLK_/21 >= 32250 && _CLK_/21 <= 4 * MHz)		
		#define PRDIV 20u
#elif (_CLK_/22 >= 32250 && _CLK_/22 <= 4 * MHz)		
		#define PRDIV 21u
#elif (_CLK_/23 >= 32250 && _CLK_/23 <= 4 * MHz)		
		#define PRDIV 22u
#elif (_CLK_/24 >= 32250 && _CLK_/24 <= 4 * MHz)		
		#define PRDIV 23u
#elif (_CLK_/25 >= 32250 && _CLK_/25 <= 4 * MHz)		
		#define PRDIV 24u
#endif

#if KNOW_DIV_CLK
	#undef PRDIV
	#define PRDIV 		19u
#endif 

#ifdef PRDIV
	#define PLLref		_CLK_ / (PRDIV + 1)
	#if (PLLref * 24  == SYSTEM_CLK)		
		#define VIDV	0u
	#elif (PLLref * 25  == SYSTEM_CLK)		
		#define VIDV	1u
	#elif (PLLref * 26  == SYSTEM_CLK)		
		#define VIDV	2u
	#elif (PLLref * 27  == SYSTEM_CLK)		
		#define VIDV	3u
	#elif (PLLref * 28  == SYSTEM_CLK)		
		#define VIDV	4u
	#elif (PLLref * 29  == SYSTEM_CLK)		
		#define VIDV	5u
	#elif (PLLref * 30  == SYSTEM_CLK)		
		#define VIDV	6u
	#elif (PLLref * 31  == SYSTEM_CLK)		
		#define VIDV	7u
	#elif (PLLref * 32  == SYSTEM_CLK)		
		#define VIDV	8u
	#elif (PLLref * 33  == SYSTEM_CLK)		
		#define VIDV	9u
	#elif (PLLref * 34  == SYSTEM_CLK)		
		#define VIDV	10u
	#elif (PLLref * 35  == SYSTEM_CLK)		
		#define VIDV	11u
	#elif (PLLref * 36  == SYSTEM_CLK)		
		#define VIDV	12u
	#elif (PLLref * 37  == SYSTEM_CLK)		
		#define VIDV	13u
	#elif (PLLref * 38  == SYSTEM_CLK)		
		#define VIDV	14u
	#elif (PLLref * 39  == SYSTEM_CLK)		
		#define VIDV	15u
	#elif (PLLref * 40  == SYSTEM_CLK)		
		#define VIDV	16u
	#elif (PLLref * 41  == SYSTEM_CLK)		
		#define VIDV	17u
	#elif (PLLref * 42  == SYSTEM_CLK)		
		#define VIDV	18u
	#elif (PLLref * 43  == SYSTEM_CLK)		
		#define VIDV	19u
	#elif (PLLref * 44  == SYSTEM_CLK)		
		#define VIDV	20u
	#elif (PLLref * 45  == SYSTEM_CLK)		
		#define VIDV	21u
	#elif (PLLref * 46  == SYSTEM_CLK)		
		#define VIDV	22u
	#elif (PLLref * 47  == SYSTEM_CLK)		
		#define VIDV	23u
	#elif (PLLref * 48  == SYSTEM_CLK)		
		#define VIDV	24u
	#elif (PLLref * 49  == SYSTEM_CLK)		
		#define VIDV	25u
	#elif (PLLref * 50  == SYSTEM_CLK)		
		#define VIDV	26u
	#elif (PLLref * 51  == SYSTEM_CLK)		
		#define VIDV	27u
	#elif (PLLref * 52  == SYSTEM_CLK)		
		#define VIDV	28u
	#elif (PLLref * 53  == SYSTEM_CLK)		
		#define VIDV	29u
	#elif (PLLref * 54  == SYSTEM_CLK)		
		#define VIDV	30u
	#elif (PLLref * 55  == SYSTEM_CLK)		
		#define VIDV	31u
	#endif
#endif
/*******************************************************************************
* Types Definitions
*******************************************************************************/
typedef enum{	//All clocking modes
	e_FEI,		//FLL engaged internal
	e_FEE,		//FLL Engaged External
	e_FBI,		//FLL bypassed internal
	e_BLPI,		//Bypassed low power internal
	e_FBE,		//FLL bypassed External
	e_BLPE,		//Bypassed low power External
	e_PBE,		//PLL bypassed External
	e_PEE		//PLL Engaged External
}eModeCLK_t;	//Clocking Modes select

typedef struct{
	eModeCLK_t sActualMode;
	eModeCLK_t sWhishedMode;
}sModeCloking_t;

/*******************************************************************************
* Global function prototypes
*******************************************************************************/
void vfn_MCG_Init(void);

/*******************************************************************************
* Local function prototypes
*******************************************************************************/
static void v_fn_MCG_Modetransition(eModeCLK_t, eModeCLK_t);
static void vfn_FEI(void);
static void vfn_FEE(void);
static void vfn_FBI(void);
static void vfn_FBE(void);
static void vfn_PBE(void);
static void vfn_PEE(void);
static void vfn_BLPE(void);
static void vfn_BLPI(void);

/*******************************************************************************
* ISR functions prototypes
*******************************************************************************/

#endif /* MCG_H_ */
